package conf

import (
	"flag"
	"time"

	"github.com/spf13/viper"
)

var file string
var conf *viper.Viper

// init函数在包初始化时自动执行
func init() {
	// 使用flag.StringVar函数定义一个名为file的变量，它接收一个字符串类型的值
	// 参数"f"是命令行参数的名称，"config.yaml"是默认值，"config file"是描述性说明
	flag.StringVar(&file, "f", "config.yaml", "config file")

	// 解析命令行参数并存储到flag.CommandLine.ParsedArgs()中
	flag.Parse()
}

// conf.go

// Init 函数用于初始化配置管理器
func Init() error {
	// 创建一个新的 Viper 实例，Viper 是一个用于处理配置信息的库
	conf = viper.New()
	// 设置配置文件的路径
	conf.SetConfigFile(file)
	// 读取配置文件，如果读取过程中出现错误，则返回该错误
	if err := conf.ReadInConfig(); err != nil {
		return err
	}

	// 如果一切正常，返回 nil 表示初始化成功
	return nil
}

// Instance 获取配置实例
//
//	@return *viper.Viper
func Instance() *viper.Viper {
	return conf
}

// GetString 获取字符串类型的配置
//
//	@param key
//	@return string
func GetString(key string) string {
	return conf.GetString(key)
}

// GetInt 获取 int 类型的配置
//
//	@param key
//	@return int
func GetInt(key string) int {
	return conf.GetInt(key)
}

// Get can retrieve any value given the key to use.
// Get is case-insensitive for a key.
// Get has the behavior of returning the value associated with the first
// place from where it is set. Viper will check in the following order:
// override, flag, env, config file, key/value store, default
//
// Get returns an interface. For a specific value use one of the Get____ methods.
func Get(key string) any { return conf.Get(key) }

// Sub returns new Viper instance representing a sub tree of this instance.
// Sub is case-insensitive for a key.
func Sub(key string) *viper.Viper { return conf.Sub(key) }

// GetBool returns the value associated with the key as a boolean.
func GetBool(key string) bool { return conf.GetBool(key) }

// GetInt32 returns the value associated with the key as an integer.
func GetInt32(key string) int32 { return conf.GetInt32(key) }

// GetInt64 returns the value associated with the key as an integer.
func GetInt64(key string) int64 { return conf.GetInt64(key) }

// GetUint returns the value associated with the key as an unsigned integer.
func GetUint(key string) uint { return conf.GetUint(key) }

// GetUint16 returns the value associated with the key as an unsigned integer.
func GetUint16(key string) uint16 { return conf.GetUint16(key) }

// GetUint32 returns the value associated with the key as an unsigned integer.
func GetUint32(key string) uint32 { return conf.GetUint32(key) }

// GetUint64 returns the value associated with the key as an unsigned integer.
func GetUint64(key string) uint64 { return conf.GetUint64(key) }

// GetFloat64 returns the value associated with the key as a float64.
func GetFloat64(key string) float64 { return conf.GetFloat64(key) }

// GetTime returns the value associated with the key as time.
func GetTime(key string) time.Time { return conf.GetTime(key) }

// GetDuration returns the value associated with the key as a duration.
func GetDuration(key string) time.Duration { return conf.GetDuration(key) }

// GetIntSlice returns the value associated with the key as a slice of int values.
func GetIntSlice(key string) []int { return conf.GetIntSlice(key) }

// GetStringSlice returns the value associated with the key as a slice of strings.
func GetStringSlice(key string) []string { return conf.GetStringSlice(key) }

// GetStringMap returns the value associated with the key as a map of interfaces.
func GetStringMap(key string) map[string]any { return conf.GetStringMap(key) }

// GetStringMapString returns the value associated with the key as a map of strings.
func GetStringMapString(key string) map[string]string { return conf.GetStringMapString(key) }

// GetStringMapStringSlice returns the value associated with the key as a map to a slice of strings.
func GetStringMapStringSlice(key string) map[string][]string {
	return conf.GetStringMapStringSlice(key)
}

// GetSizeInBytes returns the size of the value associated with the given key
// in bytes.
func GetSizeInBytes(key string) uint { return conf.GetSizeInBytes(key) }

// UnmarshalKey takes a single key and unmarshals it into a Struct.
func UnmarshalKey(key string, rawVal any, opts ...viper.DecoderConfigOption) error {
	return conf.UnmarshalKey(key, rawVal, opts...)
}

// Unmarshal unmarshals the config into a Struct. Make sure that the tags
// on the fields of the structure are properly set.
func Unmarshal(rawVal any, opts ...viper.DecoderConfigOption) error {
	return conf.Unmarshal(rawVal, opts...)
}
